package net.sk.china.city.talk.service.impl.system;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import net.sk.china.common.response.CommonPage;
import net.sk.china.city.talk.dao.system.SystemAdminDao;
import net.sk.china.city.talk.model.system.CityAdmin;
import net.sk.china.city.talk.model.system.CityRole;
import net.sk.china.city.talk.request.system.SystemAdminAddRequest;
import net.sk.china.city.talk.request.system.SystemAdminRequest;
import net.sk.china.city.talk.request.system.SystemAdminUpdateRequest;
import net.sk.china.city.talk.response.system.SystemAdminResponse;
import net.sk.china.city.talk.service.system.SystemAdminService;
import net.sk.china.city.talk.service.system.SystemRoleService;
import net.sk.china.city.talk.utils.ValidateFormUtil;
import net.sk.china.common.exception.TalkException;
import net.sk.china.common.request.PageParamRequest;
import net.sk.china.common.utils.TalkUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * SystemAdminServiceImpl 接口实现
 * +----------------------------------------------------------------------
 * // | Talk To [ 聊来改善地区金融服务环境，助力企业发展 ]
 * // +----------------------------------------------------------------------
 * // | Copyright (c) 2018-2024 聊来 All rights reserved.
 * // +----------------------------------------------------------------------
 * // | Licensed ( <a href="http://www.apache.org/licenses/LICENSE-2.0">apache</a> )
 * // +----------------------------------------------------------------------
 * // | @Author: 聊来 <18970881148@qq.com>
 * // +----------------------------------------------------------------------
 * // | DateTime: 2024/6/2 16:29
 * // +----------------------------------------------------------------------
 */

@Service
public class SystemAdminServiceImpl extends ServiceImpl<SystemAdminDao, CityAdmin> implements SystemAdminService {

    @Resource
    private SystemAdminDao dao;

    private final SystemRoleService systemRoleService;

    private final TransactionTemplate transactionTemplate;

    public SystemAdminServiceImpl(SystemRoleService systemRoleService, TransactionTemplate transactionTemplate) {
        this.systemRoleService = systemRoleService;
        this.transactionTemplate = transactionTemplate;
    }

    /**
     * 后台管理员列表
     * @param request 请求参数
     * @param pageParamRequest 分页参数
     * @return {@code PageInfo<SystemAdminResponse>}
     */
    @Override
    public PageInfo<SystemAdminResponse> getList(SystemAdminRequest request, PageParamRequest pageParamRequest) {
        Page<SystemAdminResponse> adminPage = PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());

        LambdaQueryWrapper<CityAdmin> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotBlank(request.getRoles())) {
            lambdaQueryWrapper.eq(CityAdmin::getRoles, request.getRoles());
        }
        if (ObjectUtil.isNotNull(request.getStatus())) {
            lambdaQueryWrapper.eq(CityAdmin::getStatus, request.getStatus());
        }
        if (StrUtil.isNotBlank(request.getRealName())) {
            lambdaQueryWrapper.and(i -> i.like(CityAdmin::getRealName, request.getRealName())
                    .or().like(CityAdmin::getAccount, request.getRealName()));
        }
        List<CityAdmin> cityAdmin = dao.selectList(lambdaQueryWrapper);

        List<SystemAdminResponse> systemAdminResponse = new ArrayList<>();
        List<CityRole> roleList = systemRoleService.getAllList();
        for (CityAdmin admin : cityAdmin) {
            SystemAdminResponse sar = new SystemAdminResponse();
            BeanUtils.copyProperties(admin, sar);
            sar.setLastTime(admin.getUpdateTime());
            if (StrUtil.isBlank(admin.getRoles())) { continue; }
            List<Integer> roleIds = TalkUtil.stringToArrayInt(admin.getRoles());
            List<String> roleNames = new ArrayList<>();
            for (Integer roleId : roleIds) {
                List<CityRole> hasRoles = roleList.stream().filter(e -> e.getId().equals(roleId)).collect(Collectors.toList());
                if (hasRoles.size()> 0) {
                    roleNames.add(hasRoles.stream().map(CityRole::getRoleName).collect(Collectors.joining(",")));
                }
            }
            sar.setRoleNames(StringUtils.join(roleNames,","));
            systemAdminResponse.add(sar);
        }
        return CommonPage.copyPageInfo(adminPage, systemAdminResponse);
    }

    /**
     * 新增管理员
     * @param request 请求数据
     * @return {@code Boolean}
     */
    @Override
    public Boolean saveAdmin(SystemAdminAddRequest request) {
        // 管理员名称唯一校验
        Long result = checkAccount(request.getAccount());
        if (result > 0) {
            throw new TalkException("管理员已存在");
        }
        // 如果有手机号，校验手机号
        if (StrUtil.isNotBlank(request.getPhone())) {
            ValidateFormUtil.isPhoneException(request.getPhone());
        }

        CityAdmin cityAdmin = new CityAdmin();
        BeanUtils.copyProperties(request, cityAdmin);

        String pwd = TalkUtil.encryptPassword(cityAdmin.getPwd(), cityAdmin.getAccount());
        cityAdmin.setPwd(pwd);

        Boolean execute = transactionTemplate.execute(e -> {
            save(cityAdmin);

            return Boolean.TRUE;
        });

        return ObjectUtil.isNotNull(execute) && execute ? Boolean.TRUE : Boolean.FALSE;
    }

    /**
     * 更新管理员
     * @param request 请求数据
     * @return {@code Boolean}
     */
    @Override
    public Boolean updateAdmin(SystemAdminUpdateRequest request) {
        getDetail(request.getId());
        verifyAccount(request.getId(), request.getAccount());
        // 如果有手机号，校验手机号
        if (StrUtil.isNotBlank(request.getPhone())) {
            ValidateFormUtil.isPhoneException(request.getPhone());
        }
        CityAdmin cityAdmin = new CityAdmin();
        BeanUtils.copyProperties(request, cityAdmin);
        cityAdmin.setPwd(null);
        if (StrUtil.isNotBlank(request.getPwd())) {
            String pwd = TalkUtil.encryptPassword(request.getPwd(), request.getAccount());
            cityAdmin.setPwd(pwd);
        }
        Boolean execute = transactionTemplate.execute(e -> {
            updateById(cityAdmin);

            return Boolean.TRUE;
        });

        return ObjectUtil.isNotNull(execute) && execute ? Boolean.TRUE : Boolean.FALSE;
    }

    /**
     * 修改后台管理员状态
     * @param id 管理员id
     * @param status 状态
     * @return {@code Boolean}
     */
    @Override
    public Boolean updateStatus(Integer id, Boolean status) {
        CityAdmin cityAdmin = getDetail(id);
        if (cityAdmin.getStatus().equals(status)) {
            return true;
        }
        cityAdmin.setStatus(status);
        return updateById(cityAdmin);
    }

    /**
     * 根据idList获取Map
     * @param adminIdList id数组
     * @return {@code HashMap<Integer, SystemAdmin>}
     */
    @Override
    public HashMap<Integer, CityAdmin> getMapInId(List<Integer> adminIdList) {
        HashMap<Integer, CityAdmin> map = new HashMap<>(16);
        if (adminIdList.size() < 1) {
            return map;
        }
        LambdaQueryWrapper<CityAdmin> query = Wrappers.lambdaQuery();
        query.in(CityAdmin::getId, adminIdList);
        List<CityAdmin> cityAdminList = dao.selectList(query);
        if (cityAdminList.size() < 1) {
            return map;
        }
        for (CityAdmin cityAdmin : cityAdminList) {
            map.put(cityAdmin.getId(), cityAdmin);
        }
        return map;
    }

    /**
     * 修改后台管理员是否接收状态
     * @param id 管理员id
     * @return {@code boolean}
     */
    @Override
    public boolean updateIsSms(Integer id) {
        CityAdmin cityAdmin = getDetail(id);
        if (StrUtil.isBlank(cityAdmin.getPhone())) {
            throw new TalkException("请先为管理员添加手机号!");
        }
        return updateById(cityAdmin);
    }

    /**
     * 管理员详情
     * @param id 管理员id
     * @return {@code SystemAdmin}
     */
    @Override
    public CityAdmin getDetail(Integer id) {
        CityAdmin cityAdmin = getById(id);
        if (ObjectUtil.isNull(cityAdmin)) {
            throw new TalkException("管理员不存在");
        }
        return cityAdmin;
    }

    /**
     * 通过用户名获取信息
     * @param username 用户名
     * @return {@code SystemAdmin}
     */
    @Override
    public CityAdmin selectUserByUserName(String username) {
        LambdaQueryWrapper<CityAdmin> query = new LambdaQueryWrapper<>();
        query.eq(CityAdmin::getAccount, username);
        query.last("limit 1");

        return dao.selectOne(query);
    }

    /**
     * 管理员名称唯一校验
     * @param account 管理员账号
     * @return {@code Long}
     */
    @Override
    public Long checkAccount(String account) {
        LambdaQueryWrapper<CityAdmin> query = new LambdaQueryWrapper<>();
        query.eq(CityAdmin::getAccount, account);
        return dao.selectCount(query);
    }

    /**
     * 校验账号唯一性（管理员更新时）
     * @param id 管理员id
     * @param account 管理员账号
     */
    @Override
    public void verifyAccount(Integer id, String account) {
        LambdaQueryWrapper<CityAdmin> query = new LambdaQueryWrapper<>();
        query.ne(CityAdmin::getId, id);
        query.eq(CityAdmin::getAccount, account);
        query.last("LIMIT 1");
        CityAdmin cityAdmin = dao.selectOne(query);
        if (ObjectUtil.isNotNull(cityAdmin)) {
            throw new TalkException("管理员账号已存在");
        }
    }

    /**
     * 删除管理员
     * @param id 管理员ID
     * @return {@code boolean}
     */
    @Override
    public boolean deleteById(Integer id) {
        CityAdmin cityAdmin = getById(id);
        if (ObjectUtil.isNull(cityAdmin)) {
            throw new TalkException("管理员不存在或已经被删除");
        }

        return removeById(id);
    }
}
